GRID_INTERP

Overview

The GRID_INTERP function performs interpolation on a two-dimensional regular (rectilinear) grid, estimating values at arbitrary points based on known data defined at grid intersections. This is useful for applications such as lookup tables, surface modeling, and spatial data analysis where values need to be estimated between measured data points.

This implementation wraps SciPy’s RegularGridInterpolator class from the scipy.interpolate module. Unlike unstructured interpolation methods (such as LinearNDInterpolator), RegularGridInterpolator exploits the regular grid structure to avoid expensive triangulation, making it significantly faster for gridded data.

The function supports two interpolation methods:

  • Linear interpolation: Performs bilinear interpolation by computing a weighted average of the four nearest grid points. For a point (x, y) within a grid cell bounded by points (x_1, y_1) and (x_2, y_2), the interpolated value is computed as:
f(x,y) \approx \frac{1}{(x_2-x_1)(y_2-y_1)} \bigl[ f(Q_{11})(x_2-x)(y_2-y) + f(Q_{21})(x-x_1)(y_2-y) + f(Q_{12})(x_2-x)(y-y_1) + f(Q_{22})(x-x_1)(y-y_1) \bigr]
  • Nearest-neighbor interpolation: Returns the value of the closest grid point, useful when preserving discrete values is preferred over smooth interpolation.

The bounds_error parameter controls behavior for points outside the grid domain. When set to TRUE, an error is raised for out-of-bounds queries. When FALSE, the fill_value parameter specifies the value returned for such points (defaulting to NaN).

For more details on the underlying algorithm, see the SciPy documentation and the SciPy GitHub repository.

This example function is provided as-is without any representation of accuracy.

Excel Usage

=GRID_INTERP(points_x, points_y, values, xi, grid_interp_method, bounds_error, fill_value)
  • points_x (list[list], required): 1D array of x-coordinates of the grid points
  • points_y (list[list], required): 1D array of y-coordinates of the grid points
  • values (list[list], required): 2D array of data values on the grid
  • xi (list[list], required): Points at which to interpolate data (n_points, 2)
  • grid_interp_method (str, optional, default: “linear”): Interpolation method
  • bounds_error (bool, optional, default: true): If True, raise error for out-of-bounds points
  • fill_value (float, optional, default: null): Value for out-of-bounds points when bounds_error is False

Returns (list[list]): A 2D list of interpolated values, or an error message (str) if invalid.

Examples

Example 1: Demo case 1

Inputs:

points_x points_y values xi
0 1 0 1 0 1 0.5 0.5
1 2

Excel formula:

=GRID_INTERP({0,1}, {0,1}, {0,1;1,2}, {0.5,0.5})

Expected output:

Result
1

Example 2: Demo case 2

Inputs:

points_x points_y values xi grid_interp_method
0 1 2 0 1 1 2 0.4 0.6 nearest
3 4
5 6

Excel formula:

=GRID_INTERP({0,1,2}, {0,1}, {1,2;3,4;5,6}, {0.4,0.6}, "nearest")

Expected output:

Result
2

Example 3: Demo case 3

Inputs:

points_x points_y values xi
0 1 0 1 0 1 0 0
2 3 1 1
0.5 0.5

Excel formula:

=GRID_INTERP({0,1}, {0,1}, {0,1;2,3}, {0,0;1,1;0.5,0.5})

Expected output:

Result
0
3
1.5

Example 4: Demo case 4

Inputs:

points_x points_y values xi bounds_error fill_value
0 1 0 1 1 2 0.5 0.5 false -999
3 4 1.5 1.5

Excel formula:

=GRID_INTERP({0,1}, {0,1}, {1,2;3,4}, {0.5,0.5;1.5,1.5}, FALSE, -999)

Expected output:

Result
2.5
-999

Python Code

import math
import numpy as np
from scipy.interpolate import RegularGridInterpolator as scipy_RegularGridInterpolator

def grid_interp(points_x, points_y, values, xi, grid_interp_method='linear', bounds_error=True, fill_value=None):
    """
    Interpolator on a regular grid in 2D.

    See: https://docs.scipy.org/doc/scipy/reference/generated/scipy.interpolate.RegularGridInterpolator.html

    This example function is provided as-is without any representation of accuracy.

    Args:
        points_x (list[list]): 1D array of x-coordinates of the grid points
        points_y (list[list]): 1D array of y-coordinates of the grid points
        values (list[list]): 2D array of data values on the grid
        xi (list[list]): Points at which to interpolate data (n_points, 2)
        grid_interp_method (str, optional): Interpolation method Valid options: Linear, Nearest. Default is 'linear'.
        bounds_error (bool, optional): If True, raise error for out-of-bounds points Default is True.
        fill_value (float, optional): Value for out-of-bounds points when bounds_error is False Default is None.

    Returns:
        list[list]: A 2D list of interpolated values, or an error message (str) if invalid.
    """
    def to2d(x):
        return [[x]] if not isinstance(x, list) else x

    def flatten(arr):
        return [item for sublist in arr for item in sublist]

    # Normalize 2D list inputs
    points_x = to2d(points_x)
    points_y = to2d(points_y)
    values = to2d(values)
    xi = to2d(xi)

    # Validate grid_interp_method parameter
    valid_methods = ["linear", "nearest"]
    if not isinstance(grid_interp_method, str):
        return "Invalid input: grid_interp_method must be a string."
    if grid_interp_method not in valid_methods:
        return f"Invalid input: grid_interp_method must be one of {valid_methods}."

    # Validate bounds_error parameter
    if not isinstance(bounds_error, bool):
        return "Invalid input: bounds_error must be a boolean."

    # Validate fill_value parameter
    if fill_value is not None:
        try:
            fill_value = float(fill_value)
            if math.isnan(fill_value):
                # NaN is allowed as fill_value
                pass
            elif math.isinf(fill_value):
                return "Invalid input: fill_value must be finite or NaN."
        except (TypeError, ValueError):
            return "Invalid input: fill_value must be a number or None."
    else:
        fill_value = float("nan")

    try:
        # Flatten points_x and points_y
        points_x_flat = flatten(points_x)
        points_y_flat = flatten(points_y)

        # Validate points are numeric
        for i, val in enumerate(points_x_flat):
            if not isinstance(val, (int, float)):
                return f"Invalid input: points_x[{i}] must be numeric."
            if math.isnan(val) or math.isinf(val):
                return f"Invalid input: points_x[{i}] must be finite."

        for i, val in enumerate(points_y_flat):
            if not isinstance(val, (int, float)):
                return f"Invalid input: points_y[{i}] must be numeric."
            if math.isnan(val) or math.isinf(val):
                return f"Invalid input: points_y[{i}] must be finite."

        # Convert values to numpy array
        values_arr = np.array(values, dtype=float)

        # Validate values dimensions
        if values_arr.ndim != 2:
            return "Invalid input: values must be a 2D array."

        if values_arr.shape[0] != len(points_x_flat):
            return f"Invalid input: values must have shape ({len(points_x_flat)}, {len(points_y_flat)})."

        if values_arr.shape[1] != len(points_y_flat):
            return f"Invalid input: values must have shape ({len(points_x_flat)}, {len(points_y_flat)})."

        # Convert xi to numpy array
        xi_arr = np.array(xi, dtype=float)

        # Validate xi dimensions
        if xi_arr.ndim != 2:
            return "Invalid input: xi must be a 2D array."

        if xi_arr.shape[1] != 2:
            return "Invalid input: xi must have shape (n_points, 2)."

        # Create interpolator
        points = (points_x_flat, points_y_flat)
        interp = scipy_RegularGridInterpolator(
            points,
            values_arr,
            method=grid_interp_method,
            bounds_error=bounds_error,
            fill_value=fill_value,
        )

        # Perform interpolation
        result = interp(xi_arr)

        # Convert result to 2D list (column vector)
        return [[float(val)] for val in result]

    except ValueError as e:
        return f"Invalid input: {e}"
    except Exception as e:
        return f"scipy.interpolate.RegularGridInterpolator error: {e}"

Online Calculator